package com.yzq.os.spider.v.controller;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.text.ParseException;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.RedirectView;

import com.yzq.os.spider.v.domain.SpiderTask;
import com.yzq.os.spider.v.service.domain.SpiderTaskService;
import com.yzq.os.spider.v.service.domain.SearchEngineService;
import com.yzq.os.spider.v.service.domain.ServerService;
import com.yzq.os.spider.v.service.job.SchedulerService;
import com.yzq.os.spider.v.util.IPUtils;

/**
 * 抓取定时任务控制器
 * @author 苑志强(xingyu_yzq@163.com)
 *
 */
@Controller
@RequestMapping("/task")
public class SpiderTaskController {

	private static Logger logger = Logger.getLogger(SpiderTaskController.class);

	private static final String ALL_LIST_TYPE = "ALL";
	private static final String LOCAL_LIST_TYPE = "LOCAL";

	/**
	 * 通知集群中的服务器重新加载定时抓取任务
	 */
	private static final String RE_LOAD_JOB_INTERFACE = "http://<SERVER_IP_ADDRESS>:8080/<CONTEXT_PATH>/admin/task/reLoadLocal";

	/**
	 * 删除集群中的某个定时抓取任务
	 */
	private static final String DELETE_JOB_INTERFACE = "http://<SERVER_IP_ADDRESS>:8080/<CONTEXT_PATH>/admin/task/deleteLocal/<TASK_ID>";

	@Autowired
	private SearchEngineService searchEngineService;

	@Autowired
	private SpiderTaskService spiderTaskService;

	@Autowired
	private SchedulerService schedulerService;

	@Autowired
	private ServerService serverService;

	/**
	 * 添加自动抓取任务
	 * @return
	 */
	@RequestMapping("/form")
	public ModelAndView form() {
		Map<String, Object> model = new HashMap<String, Object>();
		model.put("engines", searchEngineService.findUIViews());
		model.put("servers", serverService.findAll());
		return new ModelAndView("/admin/task/form", model);
	}
	
	
/**
 * 保存或更新自动抓取任务
 * @param spiderTask
 * @return
 * @throws SchedulerException
 * @throws ParseException
 * @throws IOException
 */
	@RequestMapping(method = RequestMethod.POST)
	public RedirectView save(SpiderTask spiderTask) throws SchedulerException,
			ParseException, IOException {
		if (spiderTask.getId() == null) {
			spiderTaskService.save(spiderTask);
		} else {
			spiderTaskService.update(spiderTask);
		}
		reLoadRemoteJob(spiderTask.getRunServerIp());
		return new RedirectView("task/local");
	}

	/**
	 * 通知集群服务器重新加载自动抓取任务
	 * @param runServerIp
	 * @throws IOException
	 */
	private void reLoadRemoteJob(String runServerIp) throws IOException {
		URL url = new URL(StringUtils.replaceEach(RE_LOAD_JOB_INTERFACE,
				new String[] { "<SERVER_IP_ADDRESS>", "<CONTEXT_PATH>" },
				new String[] { runServerIp, serverService.getContextPath() }));
		URLConnection conn = url.openConnection();
		InputStream in = conn.getInputStream();
		String message = IOUtils.toString(in);
		IOUtils.closeQuietly(in);
		logger.info("Re load remote job from ip[" + runServerIp + "],message["
				+ message + "]");
	}

	/**
	 * 本地重新加载自动抓取任务
	 * @return
	 * @throws SchedulerException
	 */
	@RequestMapping("/reLoadLocal")
	@ResponseBody
	public String reLoadLocalJob() throws SchedulerException {
		schedulerService.putLocalCrawlTask();
		logger.info("Re load local job.................");
		return "OK";
	}

	/**
	 * 集群自动抓取任务列表
	 * @return
	 */
	@RequestMapping()
	public ModelAndView listAll() {
		Map<String, Object> model = new HashMap<String, Object>();
		model.put("listType", ALL_LIST_TYPE);
		model.put("tasks", spiderTaskService.list());
		return new ModelAndView("/admin/task/list", model);
	}

	/**
	 * 本地服务器的自动抓取任务列表
	 * @return
	 */
	@RequestMapping("/local")
	public ModelAndView listLocal() {
		Map<String, Object> model = new HashMap<String, Object>();
		model.put("listType", LOCAL_LIST_TYPE);
		model.put("tasks",
				spiderTaskService.findLocalTasks(IPUtils.getLocalIPAddress()));
		return new ModelAndView("/admin/task/list", model);
	}

	/**
	 * 修改指定的自动抓取任务
	 * @param id
	 * @return
	 */
	@RequestMapping("/modify/{id}")
	public ModelAndView modify(@PathVariable int id) {
		Map<String, Object> model = new HashMap<String, Object>();
		SpiderTask crawlTask = spiderTaskService.loadById(id);
		model.put("engines", searchEngineService.findUIViews());
		model.put("servers", serverService.findAll());
		model.put("crawlTask", crawlTask);
		return new ModelAndView("/admin/task/form", model);
	}

	/**
	 * 集群删除指定的自动抓取任务
	 * @param id
	 * @return
	 * @throws SchedulerException
	 * @throws IOException
	 */
	@RequestMapping("/delete/{id}")
	public RedirectView deleteRemote(@PathVariable int id)
			throws SchedulerException, IOException {
		SpiderTask crawlTask = spiderTaskService.loadById(id);
		String runServerIp = crawlTask.getRunServerIp();
		String crawlTaskId = String.valueOf(id);
		URL url = new URL(StringUtils.replaceEach(DELETE_JOB_INTERFACE,
				new String[] { "<SERVER_IP_ADDRESS>", "<CONTEXT_PATH>",
						"<TASK_ID>" }, new String[] { runServerIp,
						serverService.getContextPath(), crawlTaskId }));
		URLConnection conn = url.openConnection();
		InputStream in = conn.getInputStream();
		String message = IOUtils.toString(in);
		IOUtils.closeQuietly(in);
		logger.info("Delete job from ip[" + crawlTask.getRunServerIp()
				+ "],message[" + message + "]");
		return new RedirectView("../local");
	}

	/**
	 * 本机删除指定的自动抓取任务
	 * @param id
	 * @return
	 * @throws SchedulerException
	 */
	@RequestMapping("/deleteLocal/{id}")
	@ResponseBody
	public String deleteLocal(@PathVariable int id) throws SchedulerException {
		SpiderTask crawlTask = spiderTaskService.loadById(id);
		spiderTaskService.delete(id);
		schedulerService.remove(crawlTask);
		return "OK";
	}
}
